﻿#pragma once
#include "classes.h"
#include "ReflectionException.h"
#include "LibraryNode.h"
#include "ValueNode.h"
#include "FunctionNode.h"
#include "TypeNode.h"
#include "NamespaceNode.h"
#include "TypeLibrary.h"
namespace LK
{
	namespace Reflection
	{
		ptr<TypeLibrary> GetGlobleLibrary();
		inline ptr<String> GetFullClassNameById(index_t id)
		{
			PTypeNode n = GetGlobleLibrary().GetTypeNodeByInfo(id);
			if (n==null)
			{
				return Type::GetTypeCommonInfoRef()[id].GetNameRef();
			}
			return n.GetFullName();
		}
		inline ptr<String> GetClassNameById(index_t id)
		{
			PTypeNode n = GetGlobleLibrary().GetTypeNodeByInfo(id);
			if (n==null)
			{
				return Type::GetTypeCommonInfoRef()[id].GetNameRef();
			}
			return n.GetName();
		}
	}
#ifdef SUPPORT_VARIADIC_TEMPLATES
	template<class ReturnType, class ...ArgumentsType>ReturnType DynamicCall(ptr<Object>&obj,ptr<String> const&functionName, ArgumentsType...args)
	{
		Reflection::PTypeNode tn = Reflection::GetGlobleLibrary().GetTypeNodeByInfo(obj->GetType());
		if (tn==null)Throw<PException >(L"类库中找不到指定的类型");
		Reflection::PFunctionNode node = cast<Reflection::PFunctionNode>(tn.FindNodeByNameInClass(functionName));
		if (node==null)Throw<PException >(L"类型节点中找不到指定名称的函数");
		return Reflection::FunctionNodeFastCall <ReturnType( ArgumentsType...) >::FastCall(node,obj.GetPtr(), args...);
	}
#else
#define TMPCT(x) ,class T##x
#define TMPT(x) ,T##x
#define TMPTt(x) ,T##x t##x
#define TMPt(x) ,t##x
#define TMPF(x)\
	template<class ReturnType MF3_RepeatAsc(TMPCT,2,x)>ReturnType DynamicCall(ptr<Object>&obj,ptr<String> const&functionName MF3_RepeatAsc(TMPTt,2,x)){\
		Reflection::PTypeNode tn = Reflection::GetGlobleLibrary().GetTypeNodeByInfo(Check()->GetType());\
		if (tn==null)Throw<PException >(L"类库中找不到指定的类型");\
		Reflection::PFunctionNode node = cast<Reflection::PFunctionNode>(tn.FindNodeByNameInClass(functionName));\
		if (node==null)Throw<PException >(L"类型节点中找不到指定名称的函数");\
		return Reflection::FunctionNodeFastCall <ReturnType( MF4_RepeatAsc_(T,,2,x)) >::FastCall(node, obj.GetPtr() MF3_RepeatAsc(TMPt,2,x));\
	}
	MF2_Repeatb(TMPF, _MRP_CNTM2)
#undef TMPCT
#undef TMPT
#undef TMPTt
#undef TMPt
#undef TMPF
#endif
}
